/*
 *	search.c
 *
 *	sglib.lib
 *
 *	Audio Finger Print project
 */

#define _CRT_SECURE_NO_WARNINGS

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

#include "..\sglib\spectrogram.h"

#define TOP_SIZE	20

static __int64 file_check(const __int32* bufSubstring, const __int64 sizeSubstring, const char* fname);

static __inline __int32 calcError(__int32 hash1, __int32 hash2)
{
	BINHASH h1;
	BINHASH h2;

	__int32 err = 0;

	h1.mHash = hash1;
	h2.mHash = hash2;

	err += abs(h1.mBin[0] - h2.mBin[0]);
	err += abs(h1.mBin[1] - h2.mBin[1]);
	err += abs(h1.mBin[2] - h2.mBin[2]);
	err += abs(h1.mBin[3] - h2.mBin[3]);

	return err;
}

int SG_Search(const __int32* bufSubstring, const __int64 sizeSubstring)
{
	WIN32_FIND_DATA FindFileData;
	HANDLE hFind;

	char topFname[TOP_SIZE][_MAX_PATH];
	__int64 topErr[TOP_SIZE];
	int i, j;

	hFind = FindFirstFile("*.afp", &FindFileData);
	if (hFind == INVALID_HANDLE_VALUE) 
	{
		printf("FindFirstFile failed (%d)\n", GetLastError());
		exit(1);
	} 

	for(i = 0; i < TOP_SIZE; ++i)
	{
		topErr[i] = _I64_MAX;
		topFname[i][0] = 0;
	}

	topErr[0] = file_check(bufSubstring, sizeSubstring, FindFileData.cFileName);
	strcpy(topFname[0], FindFileData.cFileName);

	while(FindNextFile(hFind,&FindFileData))
	{
		__int64 err0 = file_check(bufSubstring, sizeSubstring, FindFileData.cFileName);

		for(i = 0; i < TOP_SIZE; ++i)
		{
			if(err0 < topErr[i])
			{
				for(j = TOP_SIZE-1; j > i; --j)
				{
					topErr[j] = topErr[j-1];
					strcpy(topFname[j], topFname[j-1]);
				}
				topErr[i] = err0;
				strcpy(topFname[i], FindFileData.cFileName);
				break;
			}
		}
	}

	printf("\nTOP %d\n", TOP_SIZE);
	for(i = 0; i < TOP_SIZE; ++i)
	{
		printf("[%lld] %s file\n", topErr[i], topFname[i]);
	}

	return 0;
}

__int64 file_check(const __int32* bufSubstring, const __int64 sizeSubstring, const char* fname)
{
	FILE* finSource;
	__int32* bufSource;
	__int64 sizeSource;
	__int64 err, err0, i, j;
	const __int32* src1;
	__int32* src2;

	if(NULL == (finSource = fopen(fname, "rb")))
	{
		printf("can't open %s file\n", fname);
		exit(1);
	}

	fseek(finSource, 0, SEEK_END);
	sizeSource = _ftelli64(finSource)/sizeof(__int32);
	fseek(finSource, 0, SEEK_SET);

	if(NULL == (bufSource = (__int32*)malloc(sizeSource*sizeof(__int32))))
	{
		printf("[sizeSource] memory allocation error\n");
		exit(1);
	}

	if(sizeSource != fread(bufSource, sizeof(__int32), sizeSource, finSource))
	{
		printf("can't read file\n");
		free(bufSource);
		exit(1);
	}

	err = _I64_MAX; // error bigger than max error
	for(j = 0; j < sizeSource-sizeSubstring+1; ++j)
	{
		err0 = 0;
		src1 = bufSubstring;
		src2 = bufSource+j;
		for(i = 0; i < sizeSubstring; ++i)
		{
			err0 += calcError(*src1++,*src2++); // sglib.h
		}
		//printf("%d %d\n",j, err0);

		if(err0 < err)
		{
			err = err0;
		}
	}

	free(bufSource);

	//printf("[file_check] %s %lld\n", fname, err);

    fclose(finSource);

	return err;
}

